#include <stdlib.h>
#include "lib.h"

#include "odbc.h"
#include "missinggamenums.h"
#include "opts.h"
#include "vphand.h"

#include "SevenCardStudSQL.h"
#include "vpConn.h"
#include "SevenCardStudGame.h"
#include "stdncerr.h"


/////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn      SevenCardStudSQL::SevenCardStudSQL(VPConnection *pConn, 
///                                             ProgressiveTrackSQL *pTracker, 
///                                             Info *pInfo)
///
/// Constructor. 
///
/// @param  pConn    -   (in) the object that connects us to the client
/// @param  pTracker -   (in) the object that owns the actual database connection
/// @param  pInfo    -   (in) miscellaneous info about the current player session.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////
SevenCardStudSQL::SevenCardStudSQL(VPConnection *pConn, ProgressiveTrackSQL *pTracker, Info *pInfo)
{
    m_pConn     = pConn;
    m_pTracker  = pTracker;
    m_pInfo     = pInfo;

}


/////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn      SevenCardStudSQL::~SevenCardStudSQL()
///
/// Destructor. 
///
/////////////////////////////////////////////////////////////////////////////////////////////////////
SevenCardStudSQL::~SevenCardStudSQL()
{

}


/////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn     SevenCardStudSQL::trackNewGame(SevenCardSavedGame* pSaved, int32 *pnBalance)
///
/// Does the work of creating all database entries for a new 7 stud poker game.
///
/// @param pSaved     - (in)  contains all pertinent info about the new game.
/// @param *pnBalance - (out) the user's latest and greatest balance is returned in here.
//
/// @return VPGameBase::NewGameResult::NG_OK on success, otherwise returns code 
///         indicating cause of failure. 
///
/////////////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::trackNewGame(SevenCardSavedGame* pSaved, int32 *pnBalance)
{
    int32 nResult = VPGameBase::NG_FAILED;
    int32 nComp;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();
        nResult = createGame(
            pSaved,
            pnBalance,
            &nComp);
        m_pTracker->unlock();

        switch (nResult)
        {
            case ProgressiveTrackSQL::NoError:
                nResult = VPGameBase::NG_OK;
                break;

            case GameDBInterface::NotEnoughMoney:
                nResult = VPGameBase::NG_NOMONEY;
                break;

            default:
                nResult = VPGameBase::NG_FAILED;
                break;
        }
    }

    return nResult;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn     SevenCardStudSQL::createGame(SevenCardSavedGame* pSaved, int32 *pnBalance, int32* pnComp)
/// 
/// This private method does the actual work for "trackNewGame".  Creates all database entries for 
/// a new 7 stud poker game.
///
/// @param pSaved     - (in)  contains all pertinent info about the new game.
/// @param *pnBalance - (out) the user's latest and greatest balance is returned in here.
/// @param *pnComp    - (out) the user's latest and greatest comp value.
//
/// @return ProgresiveTrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
///////////////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::createGame(SevenCardSavedGame* pSaved, int32 *pnBalance, int32* pnComp)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 result=0;

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;

    query = conn->query();
    if (query)
    {
        query->define("exec pub_CreateGameSevenCardStud ");

        query->addParam(ServerOpts::casinoId);
        query->addParam(m_pInfo->pid);
        query->addParam(m_pInfo->machineID, ODBCQuery::BINARY);
        query->addParam(m_pInfo->forMoney);
        query->addParam(m_pInfo->sessionId, ODBCQuery::NOQUOTES);
        query->addParam((int32) (m_pInfo->forMoney ? m_pConn->getCompFactor() : 0));

        // new game info        
        query->addParam(pSaved->nBet, ODBCQuery::MONEY);               
        query->addParam(pSaved->nSideBet, ODBCQuery::MONEY);
        query->addParam(pSaved->ucSideBetRank);

        // saved game info
        query->addParam(pSaved->ucSideBetPayTable);
        query->addParam(pSaved->bSideBetEnabled);                
        query->addParam((int32)pSaved->shue.seed);
        query->addParam(pSaved->ucDeckConfiguration);
        query->addParam(m_pConn->getCreditValue());
        query->addParam(pSaved->ucPayTable);        
        query->addParam((bool8)(pSaved->ucDblUpEnabled != 0));

        if (query->exec())
        {
            while (query->getRow())
            {
                ok = query->getData(1, &result) &&
                     query->getData(2, m_pInfo->gid, VPOKER_GAMEID_SIZE) &&
                     query->getData(3, pnBalance, ODBCQuery::MONEY) &&
                     query->getData(4, pnComp);
            }
        }
        delete query;
    }
    delete conn;

    if (ok && result == 0)
    {
        return ProgressiveTrackSQL::NoError;
    }
    else if (ok && result == -1)
    {
        return NotEnoughMoney;
    }
    else
    {
        return ProgressiveTrackSQL::ExecFailed;
    }
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::trackShowAll(int32 nStep, int32 nFinalBet, int32 nPayout, int32 nSideBetPayout, 
///                                     VPHand *pDealt, uint8 aucBestCards[], int32 nPayType, 
///                                     int32 nSideBetPayType, uint8 ucDUActive, int32 *pnBalance)
///
/// This is called when the player makes their last bet of the main game and is shown all the remaining
/// cards.  If the user didn't qualify for "double up", then the game ends here.  Otherwise we just note
/// the results of the main game and let the user continue on to "double up".
///
/// (all monetary amounts are in cents)
/// @param nStep          - (in)  which wager step was the user on when they made their last bet?
/// @param nFinalBet      - (in)  the amount of the user's last bet
/// @param nPayout        - (in)  how much did the user win on the main game?
/// @param nSideBetPayout - (in)  how much did the user win on the side bet?
/// @param pDealt         - (in)  the actual cards that the user was dealt, in packed byte format.
/// @param aucBestCards   - (in)  the FIVE cards making up the best hand, out of the 7 cards that were dealt.
/// @param nPayType       - (in)  -1 for no win, otherwise the rank of the best hand.
/// @param nSideBetPayType - (in) -1 for no win on the side bet.  Otherwise the rank of the hand that won.
///                               (may not be the same as nPayType)
/// @param ucDUActive     - (in)  1 if the user will get a chance to double up.  0 if no chance.
/// @param *pnBalance     - (out) the user's latest and greatest balance is returned in here 
///                               (will not reflect user's winnings if the user still has to do "double up").
//
/// @return GameDBInterface::GameSQLError::Success on success, otherwise returns code 
///         indicating cause of failure. 
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::trackShowAll(int32 nStep, int32 nFinalBet, int32 nPayout, int32 nSideBetPayout, 
                                     VPHand *pDealt, uint8 aucBestCards[], int32 nPayType, 
                                     int32 nSideBetPayType, uint8 ucDUActive, int32 *pnBalance)
{
    int32  nResult = UnknownError;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();

        nResult = showAll(nStep, nFinalBet, nPayout, nSideBetPayout, pDealt, aucBestCards,
                          nPayType, nSideBetPayType, ucDUActive, pnBalance);

        m_pTracker->unlock();
    }

    return nResult;

}



//////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::showAll(int32 nStep, int32 nFinalBet, int32 nPayout, int32 nSideBetPayout, 
///                                VPHand *pDealt, uint8 aucBestCards[], int32 nPayType, 
///                                int32 nSideBetPayType, uint8 ucDUActive, int32 *pnBalance)
///
/// Private method called by trackShowAll to do the actual work.  
/// This is called when the player makes their last bet of the main game and is shown all the remaining
/// cards.  If the user didn't qualify for "double up", then the game ends here.  Otherwise we just note
/// the results of the main game and let the user continue on to "double up".
///
/// (all monetary amounts are in cents)
/// @param nStep          - (in)  which wager step was the user on when they made their last bet?
/// @param nFinalBet      - (in)  the amount of the user's last bet
/// @param nPayout        - (in)  how much did the user win on the main game? 
/// @param nSideBetPayout - (in)  how much did the user win on the side bet?
/// @param pDealt         - (in)  the actual cards that the user was dealt, in packed byte format.
/// @param aucBestCards   - (in)  the FIVE cards making up the best hand, out of the 7 cards that were dealt.
/// @param nPayType       - (in)  -1 for no win, otherwise the rank of the best hand.
/// @param nSideBetPayType - (in) -1 for no win on the side bet.  Otherwise the rank of the hand that won.
///                               (may not be the same as nPayType)
/// @param ucDUActive     - (in)  1 if the user will get a chance to double up.  0 if no chance.
/// @param *pnBalance     - (out) the user's latest and greatest balance is returned in here 
///                               (will not reflect user's winnings if the user still has to do "double up").
//
/// @return GameDBInterface::GameSQLError::Success on success, otherwise returns code 
///         indicating cause of failure. 
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::showAll(int32 nStep, int32 nFinalBet, int32 nPayout, int32 nSideBetPayout, 
                                VPHand *pDealt, uint8 aucBestCards[], int32 nPayType, 
                                int32 nSideBetPayType, uint8 ucDUActive, int32 *pnBalance)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nErr = -1;

    conn = m_pTracker->getConn();

    if(conn)
    {
        query = conn->query();
        if (query)
        {
            query->define("exec pub_SevenCardStudShowAll ");
            
            query->addParam(ServerOpts::casinoId);            
            query->addParam(m_pInfo->pid);
            query->addParam((bool8)(m_pInfo->forMoney != 0));
            query->addParam(m_pConn->getCreditValue());
            query->addParam(m_pInfo->gid, ODBCQuery::NOQUOTES);
            query->addParam((uint8)(nStep & 0xffL));
            query->addParam(nFinalBet, ODBCQuery::MONEY);
            query->addParam(nPayType);
            query->addParam(nPayout, ODBCQuery::MONEY);
            query->addParam(pDealt->getCards(), pDealt->getCount(), ODBCQuery::BINARY);
            query->addParam(aucBestCards, 5, ODBCQuery::BINARY);
            query->addParam((bool8)(ucDUActive != 0));            
            query->addParam(nSideBetPayout, ODBCQuery::MONEY);
            query->addParam(nSideBetPayType);

            if (query->exec())
            {
                while(query->getRow())
                {
                    if(query->numCols()>2)
                    {
                        ok = query->getData(1, &nErr)  &&
                             query->getData(2, pnBalance, ODBCQuery::MONEY);
                    }
                }
            }
        }
        delete query;
    }
    delete conn;

    int nRetVal = Success;
    
    if(!ok || nErr!=0)
    {
        if(nFinalBet > *pnBalance)
        {
            nRetVal = NotEnoughMoney;
        }
        else 
        {
            nRetVal = UnknownError;
        }
    }

    return nRetVal;
}

//////////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::trackNextBet(int32 nStep, int32 nBet, int32 *pnBalance)
///
/// This method is called for the second and third bets that the player makes, unless they hit
/// "Deal All" on those bets.  So basically it just does the logic for making a bet, without
/// the logic for creating a new game or completing a game.
///
/// (all monetary amounts are in cents)
/// @param  nStep     -   (in)  Which bet are we on?  2nd or 3rd?
/// @param  nBet      -   (in)  The amount of the bet.
/// @param  pnBalance -   (out) The user's balance after bet.
///
/// @return GameDBInterface::GameSQLError::Success on success, otherwise returns code 
///         indicating cause of failure. 
///
//////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::trackNextBet(int32 nStep, int32 nBet, int32 *pnBalance)
{
    int32  nResult = UnknownError;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();

        nResult =  nextBet(nStep, nBet, pnBalance);

        m_pTracker->unlock();
    }

    return nResult;
}



//////////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::nextBet(int32 nStep, int32 nBet, int32 *pnBalance)
///
/// Private method
/// Called for the second and third bets that the player makes, unless they hit 
/// "Deal All" on those bets.  So basically it just does the logic for making a 
/// bet, without the logic for creating a new game or completing a game.
///
/// (all monetary amounts are in cents)
/// @param  nStep     -   (in)  Which bet are we on?  2nd or 3rd?
/// @param  nBet      -   (in)  The amount of the bet.
/// @param  pnBalance -   (out) The user's balance after bet.
///
/// @return GameDBInterface::GameSQLError::Success on success, otherwise returns code 
///         indicating cause of failure. 
///
//////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::nextBet(int32 nStep, int32 nBet, int32 *pnBalance)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nSuccess = 0;

    conn = m_pTracker->getConn();

    if(conn)
    {
        query = conn->query();
        if (query)
        {
            query->define("exec pub_SevenCardStudNextBet ");
            
            query->addParam(ServerOpts::casinoId);            
            query->addParam(m_pInfo->pid);
            query->addParam((bool8)(m_pInfo->forMoney != 0));
            query->addParam(m_pInfo->gid, ODBCQuery::NOQUOTES);
            query->addParam((bool8) nStep);
            query->addParam(nBet, ODBCQuery::MONEY);

            if (query->exec())
            {                
                if (query->getRow())
                {
                    ok = query->getData(1, pnBalance, ODBCQuery::MONEY) &&
                         query->getData(2, &nSuccess);
                }
            }
        }
        delete query;
    }
    delete conn;

    int nRetVal = Success;
    
    if(!ok)
    {
        nRetVal = UnknownError;
    }
    else if(ok && nSuccess==0 && nBet>*pnBalance)
    {
        nRetVal = NotEnoughMoney;
    }
    else if(nSuccess==0)
    {
        nRetVal = UnknownError;
    }

    return nRetVal;
}


///////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::getOptions(VPokerOpts* opts, uint8 machId, int32 creditValue)
///
/// This is called when a player first connects to the game server, to get the configuration
/// options that will be in effect for the duration of the player session.
///
/// @param opts        -  (out)  we return all of the config values in here.
/// @param machId      -  (in)   machine id, used to find the correct config record in the DB
/// @param creditValue -  (in)   creditValue being played, used to find the correct config 
///                              record in the DB
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
///
///////////////////////////////////////////////////////////////////////////////////////////
int32
SevenCardStudSQL::getOptions(VPokerOpts* opts, uint8 machId, int32 creditValue)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nOrigPayTable = -1;

    localCurrency lc;

	ok = m_pTracker->getLocale(&lc) == ProgressiveTrackSQL::NoError;

    if (!ok)
    {
        return ok;
    }

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;


    // first get the standard configuration settings
    query = conn->query();
    if (query)
    {
        query->define("exec pub_SevenCardStudGetOptions ");
        query->addParam(machId, ODBCQuery::BINARY);
        query->addParam(creditValue);
        query->addParam(lc.int_curr_symbol);

        if (query->exec())
        {
            opts->payFreq = VPokerOpts::LO;
            opts->dblUpEnabled = false;

            while (query->getRow())
            {
                ok =
                    query->getData(1, &opts->payFreq)               &&
                    query->getData(2, &opts->dblUpEnabled)          &&
                    query->getData(3, &opts->bSideBetEnabled)       &&
                    query->getData(4, &opts->ucDeckConfiguration);

                // each deck config has it's own paytables...for a total of 9 
                // possible tables...3 for each deck config.
                nOrigPayTable = opts->payFreq;
                opts->payFreq = 3*opts->ucDeckConfiguration + opts->payFreq;
                opts->ucSideBetPayTable = (uint8) opts->payFreq;
            }
        }
        delete query;
    }

	//psharpless 10/20/06
	//Case: 11052  New Double Up Win Cap Logic

	//get the new global options data
	if(ok)
	{
        query = conn->query();
        if (query)
        {
			query->define("exec pub_VPokerGetOptionsGlobal ");

			if (query->exec())
			{
				while (query->getRow())
				{
					ok = query->getData(1, &opts->dlbUpCapAmount);
				}
			}
			delete query;
		}
	}

    // NOW, also get the list of supported credit values.  Normally, credit values
    // are restricted to 5, 25, 50, 100, and 500.  However, for this game, all values
    // are allowed, and we need to know what they are.  There will only be 5 though.
    if(ok)
    {
        query = conn->query();
        if (query)
        {
            query->define("exec pub_SevenCardStudGetCreditValues ");
			query->addParam(lc.int_curr_symbol);

            if (query->exec())
            {
                int nCount=0;

                // get the 5 (and ONLY 5) credit values.
                while (ok && nCount<5 && query->getRow())
                {
                    ok = query->getData(1, &opts->anCreditValues[nCount++]);                    
                }

                if(nCount!=5)
                {
                    ok=false;
                }
            }
            delete query;
        }
    }


    delete conn;

    if (ok &&
        nOrigPayTable >= VPokerOpts::LO &&
        nOrigPayTable <= VPokerOpts::HIGH)
        return ProgressiveTrackSQL::NoError;
    else
        return ProgressiveTrackSQL::ExecFailed;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn     SevenCardStudSQL::getPlayerLimits(const PID& pid, int32 gameId, 
///                                           uint8 machId, int32* compFactor)
///
/// This is really just to get the comp factor.  7 stud poker (and video poker games
/// in general) doesn't have a configurable min or max.
///
/// @param pid        -  (in)  player id, for player class limits
/// @param gameid     -  (in)  game id for 7 stud poker...currently 22.  
/// @param machid     -  (in)  machine id for this particular variant...currently only 1 machine...0.
/// @param compFactor -  (out) this is what we're after...the comp factor.
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
/////////////////////////////////////////////////////////////////////////////////////////////////
int32
SevenCardStudSQL::getPlayerLimits(const PID& pid, int32 gameId, uint8 machId, int32* compFactor)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;

    query = conn->query();
    if (query)
    {
        query->define("exec pub_lim_getPlayerLimits ");
        query->addParam(pid);
        query->addParam(gameId);
        query->addParam(machId, ODBCQuery::BINARY);

        if (query->exec())
        {
            while (query->getRow())
            {
                ok = query->getData(4, compFactor);
            }
        }
        delete query;
    }
    delete conn;

    return ok ? m_pTracker->isGameEnabled(gameId,machId) : ProgressiveTrackSQL::ExecFailed;
}




///////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::processSavedGame(VPGameBase **ppGame, int32* err)
///
/// This is called to check for unfinished games and if any are found to load them back up
/// so that they can be completed.
///
/// @param ppGame   -   (out) If a game is found and successfully reloaded, return 
///                           the game object here.
/// @param err      -   (out) if anything goes wrong with reloading the game, return 
///                           the code indicating what client response to send here.
///
/// @return true if we load a game, false if no game is found.
///
///////////////////////////////////////////////////////////////////////////////////////////
bool8
SevenCardStudSQL::processSavedGame(VPGameBase **ppGame, int32* err)
{
    SevenCardSavedGame sg;
    int32 result = ProgressiveTrackSQL::ExecFailed;
    bool8 exists;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();

        result = hasSavedGame(&sg, &exists);

        if (result == ProgressiveTrackSQL::NoError && exists)
        {
            *ppGame = new SevenCardStudGame(m_pConn, this, &sg);
            if ((*ppGame)!=NULL && (*ppGame)->initOk())
            {
                m_pTracker->unlock();
                return true;
            }

            m_pTracker->unlock();

            delete (*ppGame);
            (*ppGame) = NULL;

            *err = LOGINERR_CONTACTCUSTSERVICE;
            return false;
        }
        else
        {
            memset(m_pInfo->gid, 0xff, sizeof(VPokerGameID));

            if (ProgressiveTrackSQL::NoError == result)
            {
                m_pTracker->unlock();

                *err = 0;
                return false;            // all ok, no saved game
            }
        }

        m_pTracker->unlock();
    }
    *err = LOGINERR_CONTACTCUSTSERVICE;
    return false;
}



///////////////////////////////////////////////////////////////////////////////////////////
/// @fn  SevenCardStudSQL::hasSavedGame(SevenCardSavedGame* pDest, bool8* pbExists)
///
/// Private method called by processSavedGame to do the database check for a saved game
/// and if one is found to read in the game data.  
///
/// @param pDest    -   (out) structure to hold game data
/// @param pbExists -   (out) true if a game was found, false if no game found
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
///////////////////////////////////////////////////////////////////////////////////////////
int32
SevenCardStudSQL::hasSavedGame(SevenCardSavedGame* pDest, bool8* pbExists)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    char acOutcome[2];
    int32 nCount=0;

    *pbExists = false;

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;
    
    query = conn->query();
    if (query)
    {
        query->define("exec pub_SevenCardStudGetSavedGame ");

        query->addParam(m_pInfo->pid);
        query->addParam(m_pInfo->machineID, ODBCQuery::BINARY);
        query->addParam(m_pConn->getCreditValue());
        query->addParam(m_pInfo->forMoney);

        if (query->exec())
        {
            while (query->getRow())
            {
                uint8 ucSavedGameState = 0;

                // get the value indicating what phase the game was in
                ok = query->getData(1, &ucSavedGameState);
                
                if(ok)
                {
                    if(ucSavedGameState==1) // playing main game
                    {
                        *pbExists = true;
                        ok = query->getData(2,  m_pInfo->gid, VPOKER_GAMEID_SIZE) &&
                             query->getData(3,  &pDest->nBet, ODBCQuery::MONEY)   &&
                             query->getData(4,  &pDest->nBet_2, ODBCQuery::MONEY) &&
                             query->getData(5,  &pDest->nBet_3, ODBCQuery::MONEY) &&
                             query->getData(6,  &pDest->nBet_4, ODBCQuery::MONEY) &&
                             query->getData(7,  &pDest->ucPhase)                  &&
                             query->getData(8,  (int32 *) &(pDest->shue.seed))    &&
                             query->getData(9,  &pDest->ucPayTable)               &&
                             query->getData(10, &pDest->ucDblUpEnabled)           &&
                             query->getData(11, &pDest->bSideBetEnabled)          &&
                             query->getData(12, &pDest->ucSideBetPayTable)        &&
                             query->getData(13, &pDest->nSideBet, ODBCQuery::MONEY)    &&
                             query->getData(14, &pDest->nSideBetPayout, ODBCQuery::MONEY) &&
                             query->getData(15, &pDest->nSideBetWinType)     &&
                             query->getData(16, &pDest->ucSideBetRank)        &&
                             query->getData(17, pDest->aucBestCards, 5, &nCount)  &&
                             query->getData(18, &pDest->ucDeckConfiguration);
                        


                        pDest->eKind = (SevenCardSavedGame::SaveTypes) ucSavedGameState;
                    }
                    else if(ucSavedGameState==2)  // FIRST double up prompt, waiting for yes/no from user.
                    {
                        *pbExists = true;
                        pDest->ucPhase = 4;
                        ok = query->getData(2,  m_pInfo->gid, VPOKER_GAMEID_SIZE) &&
                             query->getData(3,  &pDest->nBet, ODBCQuery::MONEY)   &&
                             query->getData(4,  &pDest->nBet_2, ODBCQuery::MONEY) &&
                             query->getData(5,  &pDest->nBet_3, ODBCQuery::MONEY) &&
                             query->getData(6,  &pDest->nBet_4, ODBCQuery::MONEY) &&
                             query->getData(7,  &pDest->ucPayTable)               &&
                             query->getData(8,  (int32 *) &(pDest->shue.seed))    &&
                             query->getData(9,  &pDest->nDblUpOrigPayType)        &&
                             query->getData(10, &pDest->nDblUpPayout, ODBCQuery::MONEY) &&
                             query->getData(11, &pDest->bSideBetEnabled)                &&
                             query->getData(12, &pDest->ucSideBetPayTable)              &&
                             query->getData(13, &pDest->nSideBet, ODBCQuery::MONEY)     &&
                             query->getData(14, &pDest->nSideBetPayout, ODBCQuery::MONEY) &&
                             query->getData(15, &pDest->nSideBetWinType)                &&
                             query->getData(16, &pDest->ucSideBetRank)                  &&
                             query->getData(17, pDest->aucBestCards, 5, &nCount)        &&
                             query->getData(18, &pDest->ucDeckConfiguration);

                        pDest->cDblUpLastOutcome = 0;
                        pDest->eKind = (SevenCardSavedGame::SaveTypes) ucSavedGameState;
                    }
                    else if(ucSavedGameState>=3) // 3, 4, and 5 all relate to double up states OTHER than the first time yes/no prompt.
                    {
                        *pbExists = true;
                        pDest->ucPhase = 4;
                        ok = query->getData(2,  m_pInfo->gid, VPOKER_GAMEID_SIZE) &&
                             query->getData(3,  &pDest->nBet, ODBCQuery::MONEY)   &&
                             query->getData(4,  &pDest->nBet_2, ODBCQuery::MONEY) &&
                             query->getData(5,  &pDest->nBet_3, ODBCQuery::MONEY) &&
                             query->getData(6,  &pDest->nBet_4, ODBCQuery::MONEY) &&
                             query->getData(7,  (int32 *) &(pDest->shue.seed))    &&
                             query->getData(8,  &pDest->ucPayTable)               &&
                             query->getData(9,  &pDest->nDblUpOrigPayType)        &&
                             query->getData(10, &pDest->nDblUpPayout, ODBCQuery::MONEY) &&
                             query->getData(11, (int32 *) &(pDest->dblUpShue.seed))     &&
                             query->getData(12, acOutcome, 2)                     &&
                             query->getData(13, &pDest->nDblUpWins)               &&
                             query->getData(14, &pDest->nDblUpRound)              && 
                             query->getData(15, &pDest->bSideBetEnabled)          &&
                             query->getData(16, &pDest->ucSideBetPayTable)        &&
                             query->getData(17, &pDest->nSideBet, ODBCQuery::MONEY)       &&
                             query->getData(18, &pDest->nSideBetPayout, ODBCQuery::MONEY) &&
                             query->getData(19, &pDest->nSideBetWinType)          &&
                             query->getData(20, &pDest->ucSideBetRank)            &&
                             query->getData(21, pDest->aucBestCards, 5, &nCount)  &&
                             query->getData(22, &pDest->ucDeckConfiguration);


                        pDest->cDblUpLastOutcome = acOutcome[0];
                        pDest->eKind = (SevenCardSavedGame::SaveTypes) ucSavedGameState;
                    }
                } 
            }
        }
        delete query;
    }
    delete conn;

    return ok ? ProgressiveTrackSQL::NoError : ProgressiveTrackSQL::ExecFailed;
}


////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::trackDoubleUpDeny(int32 nPayout, int32 nSideBetPayout, int32* pnBalance)
///
/// Called when the user turns down the chance to play a round of double or nothing.  So, they 
/// get to keep their winnings, and the game is officially over.
///
/// @param nPayout        -   (in)  the player's actual winnings
/// @param nSideBetPayout -   (in)  the amount that the player won on the side bet, if any.
/// @param pnBalance      -   (out) player's balance after factoring everything in
///
/// @return true if all is well, false otherwise.
////////////////////////////////////////////////////////////////////////////////////////////////////
bool8
SevenCardStudSQL::trackDoubleUpDeny(int32 nPayout, int32 nSideBetPayout, int32* pnBalance)
{
    int32 nResult = ProgressiveTrackSQL::ExecFailed;
    int32 nComp;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();
        nResult = doubleUpDeny( nPayout,
                                nSideBetPayout,
                                pnBalance,
                                &nComp);
        m_pTracker->unlock();
    }

    return (bool8)(nResult == ProgressiveTrackSQL::NoError);
}



////////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::doubleUpDeny(int32 nPayout, int32 nSideBetPayout, 
///                                    int32* pnBalance, int32* pnComp)
///
/// Private method taht actually does the work for trackDoubleUpDeny.
/// Called when the user turns down the chance to play a round of double or nothing.  So, they 
/// get to keep their winnings, and the game is officially over.
///
/// @param nPayout        -   (in)  the player's actual winnings
/// @param nSideBetPayout -   (in)  the amount that the player won on the side bet, if any.
/// @param pnBalance      -   (out) player's balance after factoring everything in
/// @param pnComp         -   (out) player's comp value
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
////////////////////////////////////////////////////////////////////////////////////////////////////
int32
SevenCardStudSQL::doubleUpDeny(int32 nPayout, int32 nSideBetPayout, int32* pnBalance, int32* pnComp)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nResult=0;

    conn = m_pTracker->getConn();

    if (!conn)
        return ProgressiveTrackSQL::NoConnection;
    
    query = conn->query();
    if (query)
    {
        query->define("exec pub_SevenCardStudDblUpDeny ");

        query->addParam(ServerOpts::casinoId);
        query->addParam(m_pInfo->pid);
        query->addParam(m_pInfo->machineID, ODBCQuery::BINARY);
        query->addParam(m_pInfo->forMoney);
        query->addParam(m_pConn->getCreditValue());
        query->addParam(m_pInfo->gid, ODBCQuery::NOQUOTES);
        query->addParam(nPayout, ODBCQuery::MONEY);
        query->addParam(nSideBetPayout, ODBCQuery::MONEY);

        if (query->exec())
        {
            while (query->getRow())
            {
                ok =
                    query->getData(1, &nResult) &&
                    query->getData(2, pnBalance, ODBCQuery::MONEY) &&
                    query->getData(3, pnComp);
            }
        }
        delete query;
    }
    delete conn;

    return ok && nResult == 0 ? ProgressiveTrackSQL::NoError : ProgressiveTrackSQL::ExecFailed;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::trackDoubleUpDeal(int32 nRound, ShueSave* pShueSave, int32* pnBalance)
///
/// Called when the player has answered yes to the double up round and we've generated the cards
/// and need to save off cards for reporting purposes and also update the save game info in case
/// we have to restore.
///
/// @param nRound    -  (in)  what double up round are we on?
/// @param pShueSave -  (in)  holds relevant game state info
/// @param pnBalance -  (out) returns the player's current balance.
///
/// @return true if all is well, false otherwise.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
bool8
SevenCardStudSQL::trackDoubleUpDeal(int32 nRound, ShueSave* pShueSave, int32* pnBalance)
{
    int32 nResult = ProgressiveTrackSQL::ExecFailed;
    int32 nComp;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();
        nResult = doubleUpDeal(nRound, pShueSave, pnBalance, &nComp);
        m_pTracker->unlock();
    }

    return (bool8)(nResult == ProgressiveTrackSQL::NoError);
}


/////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::doubleUpDeal(int32 nRound, ShueSave* pShueSave, int32* pnBalance, int32* pnComp)
///
/// Private method called to do the real work for trackDoubleUpDeal.
/// Called when the player has answered yes to the double up round and we've generated the cards
/// and need to save off cards for reporting purposes and also update the save game info in case
/// we have to restore.
///
/// @param nRound    -  (in)  what double up round are we on?
/// @param pShueSave -  (in)  holds relevant game state info
/// @param pnBalance -  (out) returns the player's current balance.
/// @param pnComp    -  (out) returns player's comp value
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
////////////////////////////////////////////////////////////////////////////////////////////////////
int32
SevenCardStudSQL::doubleUpDeal(int32 nRound, ShueSave* pShueSave, int32* pnBalance, int32* pnComp)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nResult=0;

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;
    
    query = conn->query();
    if (query)
    {
        query->define("exec pub_SevenCardStudDblUpDeal ");

        query->addParam(ServerOpts::casinoId);
        query->addParam(m_pInfo->pid);
        query->addParam(m_pInfo->forMoney);
        query->addParam(m_pInfo->gid, ODBCQuery::NOQUOTES);
        query->addParam(nRound);
        query->addParam((int32)pShueSave->seed);

        if (query->exec())
        {
            while (query->getRow())
            {
                ok =
                    query->getData(1, &nResult) &&
                    query->getData(2, pnBalance, ODBCQuery::MONEY) &&
                    query->getData(3, pnComp);
            }
        }
        delete query;
    }
    delete conn;

    return ok && nResult == 0 ? ProgressiveTrackSQL::NoError : ProgressiveTrackSQL::ExecFailed;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::trackDoubleUpSelect(int32 nRound, VPHand *pDealt, uint8 ucChoice, 
///                                           uint8 ucWinResult, int32 nPayout, int32* pnBalance)
///
/// Called after the user has selected either "big" or "small".  If the user chose correctly
/// then they are offered another round of double or nothing.  If the user chose wrong, then
/// this call officially ends the game.
///
/// @param nRound      - (in)  how many double up rounds have we already played?
/// @param pDealt      - (in)  the actual cards that were dealt for the double up round, in packed format.
/// @param ucChoice    - (in)  Did the player choose big or small (1 or 0)
/// @param ucWinResult - (in)  Did the player win the round or lose?
/// @param nPayout     - (in)  how much did the player win (0 if nothing)
/// @param pnBalance   - (out) the player's balance after factoring in this win or loss.
///
/// @return true if all is well, false otherwise
/////////////////////////////////////////////////////////////////////////////////////////////////
bool8 SevenCardStudSQL::trackDoubleUpSelect(int32 nRound, VPHand *pDealt, uint8 ucChoice, 
                                            uint8 ucWinResult, int32 nPayout, int32* pnBalance)
{
    int32 nResult = ProgressiveTrackSQL::ExecFailed;
    int32 nComp;

    if (m_pTracker && m_pInfo)
    {
        m_pTracker->lock();
        nResult = doubleUpSelect(
            nRound,
            pDealt, 
            ucChoice,
            ucWinResult,
            nPayout,
            pnBalance,
            &nComp);
        m_pTracker->unlock();
    }

    return (bool8)(nResult == ProgressiveTrackSQL::NoError);
}




/////////////////////////////////////////////////////////////////////////////////////////////////
/// @fn SevenCardStudSQL::doubleUpSelect(int32 nRound, VPHand* pDealt, uint8 ucChoice, uint8 ucWinResult, 
///                                      int32 nPayout, int32* pnBalance, int32* pnComp)
///
/// Private method called by trackDoubleUpSelect to do the actual work.
/// Called after the user has selected either "big" or "small".  If the user chose correctly
/// then they are offered another round of double or nothing.  If the user chose wrong, then
/// this call officially ends the game.
///
/// @param nRound      - (in)  how many double up rounds have we already played?
/// @param pDealt      - (in)  the actual cards that were dealt for the double up round, in packed format.
/// @param ucChoice    - (in)  Did the player choose big or small (1 or 0)
/// @param ucWinResult - (in)  Did the player win the round or lose?
/// @param nPayout     - (in)  how much did the player win (0 if nothing)
/// @param pnBalance   - (out) the player's balance after factoring in this win or loss.
/// @param pnComp      - (out) the player's comp value
///
/// @return TrackSQL::NoError on success, otherwise returns code 
///         indicating cause of failure. 
///
/////////////////////////////////////////////////////////////////////////////////////////////////
int32 SevenCardStudSQL::doubleUpSelect(int32 nRound, VPHand* pDealt, uint8 ucChoice, uint8 ucWinResult, 
                                       int32 nPayout, int32* pnBalance, int32* pnComp)
{
    ODBCConnection* conn;
    ODBCQuery* query;
    bool8 ok = false;
    int32 nResult=0;

    conn = m_pTracker->getConn();
    if (!conn)
        return ProgressiveTrackSQL::NoConnection;
    
    query = conn->query();
    if (query)
    {
        query->define("exec pub_SevenCardStudDblUpSelect ");

        query->addParam(ServerOpts::casinoId);
        query->addParam(m_pInfo->pid);
        query->addParam(m_pInfo->machineID, ODBCQuery::BINARY);
        query->addParam(m_pInfo->forMoney);
        query->addParam(m_pConn->getCreditValue());
        query->addParam(m_pInfo->gid, ODBCQuery::NOQUOTES);
        query->addParam(nRound);
        query->addParam(pDealt->getCards(), pDealt->getCount(), ODBCQuery::BINARY);
        query->addParam(ucChoice);
        query->addParam(&ucWinResult, 1, ODBCQuery::BINARY);
        query->addParam(nPayout, ODBCQuery::MONEY);

        if (query->exec())
        {
            while (query->getRow())
            {
                ok =
                    query->getData(1, &nResult) &&
                    query->getData(2, pnBalance, ODBCQuery::MONEY) &&
                    query->getData(3, pnComp);
            }
        }
        delete query;
    }
    delete conn;

    return ok && nResult == 0 ? ProgressiveTrackSQL::NoError : ProgressiveTrackSQL::ExecFailed;
}
